﻿<template>
  <div class="resource-monitor-panel">
    <h2>资源监控面板</h2>
    
    <!-- 搜索和分页控制区 -->
    <div class="control-bar">
      <div class="search-box">
        <el-input
          v-model="searchKeyword"
          placeholder="输入设备ID搜索"
          clearable
          size="small"
          @input="handleSearch"
        ></el-input>
      </div>
      
      <div class="control-buttons">
        <el-button size="small" @click="addMockData" type="primary">
          <i class="el-icon-plus"></i> 添加模拟设备
        </el-button>
        <el-button size="small" @click="clearAllData" type="danger">
          <i class="el-icon-delete"></i> 清空数据
        </el-button>
      </div>
      
      <el-pagination
        v-if="filteredVehicleList.length > 0"
        small
        :current-page="currentPage"
        :page-size="pageSize"
        :total="filteredVehicleList.length"
        :page-sizes="[5, 10, 15, 20]"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      ></el-pagination>
    </div>
    
    <!-- 状态提示栏 -->
    <div class="status-bar">
      <span class="update-time">最后更新: {{ lastUpdateTime }}</span>
      <span class="device-count">设备数量: {{ vehicleList.length }}</span>
      <span 
        :class="['status-indicator', statusClass]"
        :style="{ cursor: hasError ? 'pointer' : 'default' }"
        @click="hasError && fetchResourceData()"
      >
        <i class="el-icon-loading" v-if="statusClass === 'status-loading'" style="margin-right: 4px; animation: rotate 2s linear infinite;"></i>
        {{ statusText }}
      </span>
    </div>
    
    <!-- 调试信息 -->
    <div class="debug-info" v-if="showDebug">
      <p>本地存储状态: {{ localStorageStatus }}</p>
      <p>设备数据量: {{ vehicleList.length }}</p>
      <p>历史数据量: {{ Object.keys(historyData).length }}</p>
      <button @click="forceSaveToLocalStorage">强制保存到本地</button>
      <button @click="clearLocalStorage">清除本地存储</button>
      <button @click="generateTestData">生成测试数据</button>
    </div>
    
    <!-- 设备列表 - 每行一个设备 -->
    <div class="device-list">
      <!-- 错误状态 -->
      <div class="error-state" v-if="hasError && !vehicleList.length" @click="fetchResourceData()" key="error">
        <i class="el-icon-error"></i>
        <span>加载失败，点击重试</span>
      </div>
      
      <div class="empty-state" v-if="!isLoading && !hasError && filteredVehicleList.length === 0 && vehicleList.length === 0" key="empty">
        <el-empty description="暂无资源数据">
          <el-button type="primary" @click="generateTestData">生成示例数据</el-button>
        </el-empty>
      </div>
      
      <!-- 设备卡片 - 每行一个设备 -->
      <div class="device-card" v-for="(device, index) in paginatedVehicleList" :key="'device_' + index + '_' + (device.veinsID || index)">
        <!-- 设备信息头部 -->
        <div class="device-header">
          <div class="device-info">
            <h3 class="device-id">设备 ID: {{ device.veinsID || '加载中...' }}</h3>
            <div class="device-meta">
              <span class="device-type">类型: {{ device.nodeType || '未知' }}</span>
              <span class="device-status" :class="getStatusClass(device)">
                {{ getStatusText(device) }}
              </span>
            </div>
          </div>
          
          <div class="device-stats">
            <div class="stat-item">
              <span class="stat-label">CPU</span>
              <span class="stat-value" :class="device.veinsID ? getUsageClass(device.cpu) : ''">
                {{ device.veinsID ? device.cpu.toFixed(2) + '%' : '--' }}
              </span>
            </div>
            <div class="stat-item">
              <span class="stat-label">内存</span>
              <span class="stat-value" :class="device.veinsID ? getUsageClass(device.memory) : ''">
                {{ device.veinsID ? device.memory.toFixed(2) + '%' : '--' }}
              </span>
            </div>
            <div class="stat-item">
              <span class="stat-label">上传</span>
              <span class="stat-value">
                {{ device.veinsID ? device.uploadRate.toFixed(2) + ' KB/s' : '--' }}
              </span>
            </div>
            <div class="stat-item">
              <span class="stat-label">下载</span>
              <span class="stat-value">
                {{ device.veinsID ? device.downloadRate.toFixed(2) + ' KB/s' : '--' }}
              </span>
            </div>
          </div>
        </div>
        
        <!-- 图表区域 - 直接显示两个图表 -->
        <div class="device-charts">
          <div class="chart-section">
            <div class="chart-title">CPU/内存使用率 (%)</div>
            <div :ref="el => setChartRef(`chart_cpu_device_${index}`, el)" class="chart-container-large"></div>
          </div>
          <div class="chart-section">
            <div class="chart-title">网络速率 (KB/s)</div>
            <div :ref="el => setChartRef(`chart_rate_device_${index}`, el)" class="chart-container-large"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage, ElButton } from 'element-plus'
import * as echarts from 'echarts'

// 响应式数据
const showDebug = ref(true)
const localStorageStatus = ref('未检查')
const DATA_EXPIRE_TIME = 10 * 60 * 1000
const localDataTime = ref(0)
const vehicleList = ref([])
const searchKeyword = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const historyData = ref({})
const timeLabels = ref([])
const chartInstances = ref({})
const isLoading = ref(false)
const hasError = ref(false)
const lastUpdateTime = ref('未更新')
const statusText = ref('初始化中')
const statusClass = ref('status-initial')
const refreshTimer = ref(null)

// 图表引用存储
const chartRefs = ref({})
const setChartRef = (key, el) => {
  if (el) {
    chartRefs.value[key] = el
  }
}

// 计算属性
const filteredVehicleList = computed(() => {
  if (!searchKeyword.value) {
    return vehicleList.value;
  }
  const keyword = searchKeyword.value.trim().toLowerCase();
  return vehicleList.value.filter(vehicle => 
    (vehicle.veinsID ? vehicle.veinsID.toString().toLowerCase().includes(keyword) : false)
  );
})

const paginatedVehicleList = computed(() => {
  if (vehicleList.value.length === 0 && isLoading.value) {
    return Array(pageSize.value).fill({});
  }
  
  const startIndex = (currentPage.value - 1) * pageSize.value;
  return filteredVehicleList.value.slice(startIndex, startIndex + pageSize.value);
})

// 模拟数据生成方法
const generateMockDevice = (id, type = '车辆') => {
  // 生成一些有趋势的数据，让图表看起来更真实
  const baseCpu = 20 + Math.random() * 60;
  const baseMemory = 30 + Math.random() * 50;
  const baseUpload = 100 + Math.random() * 500;
  const baseDownload = 200 + Math.random() * 800;
  
  return {
    veinsID: id,
    nodeType: type,
    cpu: Math.max(0, Math.min(100, baseCpu + (Math.random() - 0.5) * 20)),
    memory: Math.max(0, Math.min(100, baseMemory + (Math.random() - 0.5) * 15)),
    uploadRate: Math.max(0, baseUpload + (Math.random() - 0.5) * 100),
    downloadRate: Math.max(0, baseDownload + (Math.random() - 0.5) * 150)
  };
}

const generateHistoryData = (deviceId, count = 15) => {
  const history = {
    cpu: [],
    memory: [],
    uploadRate: [],
    downloadRate: []
  };
  
  // 生成有趋势的历史数据
  let lastCpu = 30 + Math.random() * 40;
  let lastMemory = 40 + Math.random() * 30;
  let lastUpload = 200 + Math.random() * 300;
  let lastDownload = 300 + Math.random() * 500;
  
  for (let i = 0; i < count; i++) {
    // 添加一些随机波动，但保持趋势
    lastCpu = Math.max(5, Math.min(95, lastCpu + (Math.random() - 0.5) * 10));
    lastMemory = Math.max(10, Math.min(90, lastMemory + (Math.random() - 0.5) * 8));
    lastUpload = Math.max(50, lastUpload + (Math.random() - 0.5) * 80);
    lastDownload = Math.max(100, lastDownload + (Math.random() - 0.5) * 120);
    
    history.cpu.push(Number(lastCpu.toFixed(2)));
    history.memory.push(Number(lastMemory.toFixed(2)));
    history.uploadRate.push(Number(lastUpload.toFixed(2)));
    history.downloadRate.push(Number(lastDownload.toFixed(2)));
  }
  
  return history;
}

const generateTimeLabels = (count = 15) => {
  const labels = [];
  const now = new Date();
  
  for (let i = count - 1; i >= 0; i--) {
    const time = new Date(now.getTime() - i * 3000); // 每3秒一个点
    labels.push(formatTime(time, true));
  }
  
  return labels;
}

// 新增的控制方法
const addMockData = () => {
  const deviceTypes = ['车辆', 'RSU', '边缘服务器', '云服务器'];
  const type = deviceTypes[Math.floor(Math.random() * deviceTypes.length)];
  const id = `${type.toLowerCase()}_${Date.now().toString().slice(-6)}`;
  
  const newDevice = generateMockDevice(id, type);
  vehicleList.value.push(newDevice);
  
  // 生成历史数据
  if (!historyData.value[id]) {
    historyData.value[id] = generateHistoryData(id);
  }
  
  // 更新时间标签
  if (timeLabels.value.length === 0) {
    timeLabels.value = generateTimeLabels();
  }
  
  ElMessage.success(`已添加设备: ${id}`);
  
  nextTick(() => {
    updateAllCharts();
    saveToLocalStorage();
  });
}

const generateTestData = () => {
  // 清空现有数据
  vehicleList.value = [];
  historyData.value = {};
  
  // 生成多个测试设备
  const testDevices = [
    generateMockDevice('vehicle_001', '车辆'),
    generateMockDevice('vehicle_002', '车辆'),
    generateMockDevice('rsu_001', 'RSU'),
    generateMockDevice('edge_server_001', '边缘服务器'),
    generateMockDevice('cloud_server_001', '云服务器')
  ];
  
  testDevices.forEach(device => {
    vehicleList.value.push(device);
    historyData.value[device.veinsID] = generateHistoryData(device.veinsID);
  });
  
  // 生成时间标签
  timeLabels.value = generateTimeLabels();
  
  lastUpdateTime.value = formatTime(new Date());
  localDataTime.value = Date.now();
  
  ElMessage.success('已生成测试数据');
  
  nextTick(() => {
    updateAllCharts();
    saveToLocalStorage();
  });
}

const clearAllData = () => {
  if (confirm('确定要清空所有数据吗？')) {
    vehicleList.value = [];
    historyData.value = {};
    timeLabels.value = [];
    Object.values(chartInstances.value).forEach(chart => chart?.dispose());
    chartInstances.value = {};
    ElMessage.info('已清空所有数据');
    saveToLocalStorage();
  }
}

const getStatusClass = (device) => {
  if (!device.veinsID) return 'status-unknown';
  
  const maxUsage = Math.max(device.cpu, device.memory);
  if (maxUsage > 80) return 'status-error';
  if (maxUsage > 60) return 'status-warning';
  return 'status-normal';
}

const getStatusText = (device) => {
  if (!device.veinsID) return '未知';
  
  const maxUsage = Math.max(device.cpu, device.memory);
  if (maxUsage > 80) return '高负载';
  if (maxUsage > 60) return '中等负载';
  return '正常';
}

// 原有的方法
const checkLocalStorageAvailability = () => {
  try {
    const testKey = 'resource_monitor_test';
    localStorage.setItem(testKey, testKey);
    localStorage.removeItem(testKey);
    localStorageStatus.value = '可用';
  } catch (e) {
    localStorageStatus.value = '不可用: ' + e.message;
    console.error('本地存储不可用:', e);
  }
}

const loadFromLocalStorage = () => {
  if (localStorageStatus.value !== '可用') {
    console.warn('本地存储不可用，无法加载数据');
    initEmptyData();
    return;
  }
  
  const storedData = localStorage.getItem('resourceMonitorData');
  if (storedData) {
    try {
      const parsed = JSON.parse(storedData);
      vehicleList.value = Array.isArray(parsed.vehicleList) ? parsed.vehicleList : [];
      historyData.value = typeof parsed.historyData === 'object' && parsed.historyData !== null 
        ? parsed.historyData 
        : {};
      timeLabels.value = Array.isArray(parsed.timeLabels) ? parsed.timeLabels : [];
      lastUpdateTime.value = parsed.lastUpdateTime || formatTime(new Date());
      localDataTime.value = parsed.saveTime || Date.now();
      
      console.log('成功加载本地数据，共', vehicleList.value.length, '条车辆数据');
      
      // 如果本地数据为空，生成示例数据
      if (vehicleList.value.length === 0) {
        generateTestData();
      }
    } catch (error) {
      console.error('本地数据解析失败，清空缓存:', error);
      localStorage.removeItem('resourceMonitorData');
      initEmptyData();
    }
  } else {
    console.log('本地无resourceMonitorData数据，初始化空数据');
    initEmptyData();
  }
}

const initEmptyData = () => {
  vehicleList.value = [];
  historyData.value = {};
  timeLabels.value = [];
  lastUpdateTime.value = formatTime(new Date());
  localDataTime.value = Date.now();
  
  // 初始时生成一些示例数据
  generateTestData();
}

const saveToLocalStorage = () => {
  if (localStorageStatus.value !== '可用') {
    console.warn('本地存储不可用，无法保存数据');
    return;
  }
  
  const dataToStore = {
    vehicleList: vehicleList.value,
    historyData: historyData.value,
    timeLabels: timeLabels.value,
    lastUpdateTime: lastUpdateTime.value,
    saveTime: Date.now()
  };
  
  try {
    const dataStr = JSON.stringify(dataToStore);
    if (dataStr.length > 5 * 1024 * 1024) { 
      console.warn('数据过大，清理部分历史数据');
      Object.keys(historyData.value).forEach(veinsID => {
        Object.keys(historyData.value[veinsID]).forEach(key => {
          if (historyData.value[veinsID][key].length > 10) {
            historyData.value[veinsID][key] = historyData.value[veinsID][key].slice(-10);
          }
        });
      });
      if (timeLabels.value.length > 10) {
        timeLabels.value = timeLabels.value.slice(-10);
      }
      saveToLocalStorage();
      return;
    }
    
    localStorage.setItem('resourceMonitorData', dataStr);
    console.log('数据已保存到本地存储，键：resourceMonitorData，大小：', (dataStr.length / 1024).toFixed(2), 'KB');
  } catch (error) {
    console.error('本地存储失败:', error);
    localStorageStatus.value = '保存失败: ' + error.message;
  }
}

const forceSaveToLocalStorage = () => {
  console.log('强制保存数据到本地存储');
  lastUpdateTime.value = formatTime(new Date());
  saveToLocalStorage();
  ElMessage.success('数据已保存到本地存储');
}

const clearLocalStorage = () => {
  if (confirm('确定要清除所有本地存储数据吗？')) {
    localStorage.removeItem('resourceMonitorData');
    initEmptyData();
    console.log('本地存储已清除');
    ElMessage.success('本地存储已清除');
  }
}

const isLocalDataValid = () => {
  const isValid = vehicleList.value.length > 0 && 
                 localDataTime.value && 
                 (Date.now() - localDataTime.value) < DATA_EXPIRE_TIME;
  console.log('本地数据有效性:', isValid);
  return isValid;
}

const startRefreshTimer = () => {
  refreshTimer.value = setInterval(() => {
    updateMockData();
  }, 3000);
}

const updateMockData = () => {
  if (vehicleList.value.length === 0) return;
  
  // 更新所有设备的实时数据
  vehicleList.value.forEach(device => {
    if (device.veinsID) {
      const history = historyData.value[device.veinsID];
      if (history) {
        // 基于历史数据的最后值生成新数据，保持连续性
        const lastCpu = history.cpu[history.cpu.length - 1] || device.cpu;
        const lastMemory = history.memory[history.memory.length - 1] || device.memory;
        const lastUpload = history.uploadRate[history.uploadRate.length - 1] || device.uploadRate;
        const lastDownload = history.downloadRate[history.downloadRate.length - 1] || device.downloadRate;
        
        device.cpu = Math.max(0, Math.min(100, lastCpu + (Math.random() - 0.5) * 8));
        device.memory = Math.max(0, Math.min(100, lastMemory + (Math.random() - 0.5) * 6));
        device.uploadRate = Math.max(0, lastUpload + (Math.random() - 0.5) * 60);
        device.downloadRate = Math.max(0, lastDownload + (Math.random() - 0.5) * 100);
        
        // 更新历史数据
        updateHistoryData([device]);
      }
    }
  });
  
  // 更新时间标签
  const currentTime = formatTime(new Date(), true);
  if (!timeLabels.value.includes(currentTime)) {
    timeLabels.value.push(currentTime);
  }
  
  if (timeLabels.value.length > 15) {
    timeLabels.value.shift();
  }
  
  lastUpdateTime.value = formatTime(new Date());
  statusText.value = '数据已更新（模拟数据）';
  statusClass.value = 'status-normal';
  
  nextTick(() => {
    updateAllCharts();
    saveToLocalStorage();
  });
}

const fetchResourceData = async () => {
  // 使用模拟数据更新
  updateMockData();
}

const mergeNewData = (newResources) => {
  newResources.forEach(newItem => {
    const existingIndex = vehicleList.value.findIndex(
      item => item.veinsID === newItem.veinsID
    );
    if (existingIndex > -1) {
      vehicleList.value[existingIndex] = { ...vehicleList.value[existingIndex], ...newItem };
    } else {
      vehicleList.value.push(newItem);
    }
  });
  
  updateHistoryData(newResources);
}

const updateHistoryData = (newVehicles) => {
  if (newVehicles.length === 0) return;
  
  newVehicles.forEach(vehicle => {
    const { veinsID, cpu, memory, uploadRate, downloadRate } = vehicle;
    if (!veinsID) return;
    
    if (!historyData.value[veinsID]) {
      historyData.value[veinsID] = {
        cpu: [],
        memory: [],
        uploadRate: [],
        downloadRate: []
      };
    }
    
    historyData.value[veinsID].cpu.push(cpu);
    historyData.value[veinsID].memory.push(memory);
    historyData.value[veinsID].uploadRate.push(uploadRate);
    historyData.value[veinsID].downloadRate.push(downloadRate);
    
    Object.keys(historyData.value[veinsID]).forEach(key => {
      if (historyData.value[veinsID][key].length > 15) {
        historyData.value[veinsID][key].shift();
      }
    });
  });
}

const updateAllCharts = () => {
  const currentIndexes = paginatedVehicleList.value.map((_, i) => i);
  
  Object.keys(chartInstances.value).forEach(key => {
    const index = parseInt(key.match(/_device_(\d+)/)?.[1] || -1);
    if (!currentIndexes.includes(index)) {
      chartInstances.value[key]?.dispose();
      delete chartInstances.value[key];
    }
  });
  
  paginatedVehicleList.value.forEach((device, index) => {
    initOrUpdateChart(index, 'cpu', !!device.veinsID);
    initOrUpdateChart(index, 'rate', !!device.veinsID);
  });
}

const initOrUpdateChart = (index, type, hasData = false) => {
  const refName = `chart_${type}_device_${index}`;
  const chartContainer = chartRefs.value[refName];
  if (!chartContainer) {
    return;
  }
  
  const instanceKey = `${type}_device_${index}`;
  
  if (chartInstances.value[instanceKey]) {
    const oldContainer = chartInstances.value[instanceKey].getDom();
    if (oldContainer !== chartContainer) {
      chartInstances.value[instanceKey].dispose();
      chartInstances.value[instanceKey] = null;
    }
  }
  
  if (!chartInstances.value[instanceKey]) {
    chartInstances.value[instanceKey] = echarts.init(chartContainer);
  }
  const chart = chartInstances.value[instanceKey];
  
  let history = {
    cpu: [],
    memory: [],
    uploadRate: [],
    downloadRate: []
  };
  
  const device = paginatedVehicleList.value[index];
  if (hasData && device.veinsID && historyData.value[device.veinsID]) {
    history = historyData.value[device.veinsID];
  }
  
  const timeLabelsToUse = hasData ? timeLabels.value : Array(15).fill('');
  const isDataValid = hasData && history[type === 'cpu' ? 'cpu' : 'uploadRate'].length > 0;
  
  const option = type === 'cpu' 
    ? getCpuChartOption(history, timeLabelsToUse, isDataValid) 
    : getRateChartOption(history, timeLabelsToUse, isDataValid);
  
  chart.setOption(option, true);
}

const getCpuChartOption = (history, timeLabels, hasData) => {
  return {
    tooltip: { 
      trigger: 'axis', 
      axisPointer: { type: 'cross' },
      formatter: '{b}<br/>{a}: {c}%'
    },
    legend: { 
      data: ['CPU使用率(%)', '内存使用率(%)'], 
      top: 5, 
      textStyle: { fontSize: 12, color: 'rgba(255, 255, 255, 0.8)' } 
    },
    grid: { left: '3%', right: '4%', bottom: '10%', top: '20%', containLabel: true },
    xAxis: {
      type: 'category',
      data: timeLabels,
      axisLabel: { 
        rotate: 30, 
        interval: 0, 
        fontSize: 10,
        color: 'rgba(255, 255, 255, 0.7)'
      },
      axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } }
    },
    yAxis: {
      type: 'value',
      name: '使用率(%)',
      min: 0,
      max: 100,
      axisLabel: { 
        formatter: '{value}%', 
        fontSize: 10,
        color: 'rgba(255, 255, 255, 0.7)'
      },
      axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } },
      splitLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.1)' } }
    },
    series: [
      {
        name: 'CPU使用率(%)',
        type: 'line',
        data: hasData ? history.cpu : Array(timeLabels.length).fill(0),
        symbol: 'circle',
        symbolSize: 4,
        lineStyle: { width: 2, color: '#1890ff' },
        itemStyle: { color: '#1890ff' },
        areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
          offset: 0, color: 'rgba(24, 144, 255, 0.3)'
        }, {
          offset: 1, color: 'rgba(24, 144, 255, 0)'
        }])}
      },
      {
        name: '内存使用率(%)',
        type: 'line',
        data: hasData ? history.memory : Array(timeLabels.length).fill(0),
        symbol: 'circle',
        symbolSize: 4,
        lineStyle: { width: 2, color: '#22c55e' },
        itemStyle: { color: '#22c55e' },
        areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
          offset: 0, color: 'rgba(34, 197, 94, 0.3)'
        }, {
          offset: 1, color: 'rgba(34, 197, 94, 0)'
        }])}
      }
    ],
    backgroundColor: 'transparent'
  };
}

const getRateChartOption = (history, timeLabels, hasData) => {
  return {
    tooltip: { 
      trigger: 'axis', 
      axisPointer: { type: 'cross' },
      formatter: '{b}<br/>{a}: {c} KB/s'
    },
    legend: { 
      data: ['上传速率(KB/s)', '下载速率(KB/s)'], 
      top: 5, 
      textStyle: { fontSize: 12, color: 'rgba(255, 255, 255, 0.8)' } 
    },
    grid: { left: '3%', right: '4%', bottom: '10%', top: '20%', containLabel: true },
    xAxis: {
      type: 'category',
      data: timeLabels,
      axisLabel: { 
        rotate: 30, 
        interval: 0, 
        fontSize: 10,
        color: 'rgba(255, 255, 255, 0.7)'
      },
      axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } }
    },
    yAxis: {
      type: 'value',
      name: '速率(KB/s)',
      min: 0,
      axisLabel: { 
        formatter: '{value}', 
        fontSize: 10,
        color: 'rgba(255, 255, 255, 0.7)'
      },
      axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } },
      splitLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.1)' } }
    },
    series: [
      {
        name: '上传速率(KB/s)',
        type: 'line',
        data: hasData ? history.uploadRate : Array(timeLabels.length).fill(0),
        symbol: 'circle',
        symbolSize: 4,
        lineStyle: { width: 2, color: '#f97316' },
        itemStyle: { color: '#f97316' },
        areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
          offset: 0, color: 'rgba(249, 115, 22, 0.3)'
        }, {
          offset: 1, color: 'rgba(249, 115, 22, 0)'
        }])}
      },
      {
        name: '下载速率(KB/s)',
        type: 'line',
        data: hasData ? history.downloadRate : Array(timeLabels.length).fill(0),
        symbol: 'circle',
        symbolSize: 4,
        lineStyle: { width: 2, color: '#ef4444' },
        itemStyle: { color: '#ef4444' },
        areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
          offset: 0, color: 'rgba(239, 68, 68, 0.3)'
        }, {
          offset: 1, color: 'rgba(239, 68, 68, 0)'
        }])}
      }
    ],
    backgroundColor: 'transparent'
  };
}

const getUsageClass = (value) => {
  if (value > 80) return 'high-usage';
  if (value > 50) return 'medium-usage';
  return 'normal-usage';
}

const handleResize = () => {
  paginatedVehicleList.value.forEach((_, index) => {
    ['cpu', 'rate'].forEach(type => {
      const instanceKey = `${type}_device_${index}`;
      chartInstances.value[instanceKey]?.resize();
    });
  });
}

const formatTime = (date, isShort = false) => {
  const hours = date.getHours().toString().padStart(2, '0');
  const minutes = date.getMinutes().toString().padStart(2, '0');
  const seconds = date.getSeconds().toString().padStart(2, '0');
  
  if (isShort) {
    return `${hours}:${minutes}:${seconds}`;
  }
  
  const year = date.getFullYear();
  const month = (date.getMonth() + 1).toString().padStart(2, '0');
  const day = date.getDate().toString().padStart(2, '0');
  
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

const handleSearch = () => {
  currentPage.value = 1;
  Object.values(chartInstances.value).forEach(chart => chart?.dispose());
  chartInstances.value = {};
  nextTick(() => {
    updateAllCharts();
  });
}

const handleSizeChange = (val) => {
  pageSize.value = val;
  currentPage.value = 1;
  Object.values(chartInstances.value).forEach(chart => chart?.dispose());
  chartInstances.value = {};
  nextTick(() => {
    updateAllCharts();
  });
}

const handleCurrentChange = (val) => {
  currentPage.value = val;
  Object.values(chartInstances.value).forEach(chart => chart?.dispose());
  chartInstances.value = {};
  nextTick(() => {
    updateAllCharts();
  });
}

// 生命周期
onMounted(() => {
  checkLocalStorageAvailability();
  loadFromLocalStorage();
  
  if (isLocalDataValid()) {
    console.log('使用本地缓存数据');
    statusText.value = '使用本地缓存数据';
    statusClass.value = 'status-normal';
    nextTick(() => {
      updateAllCharts();
    });
  } else {
    console.log('本地数据无效或过期，请求新数据');
    fetchResourceData();
  }
  
  startRefreshTimer();
  window.addEventListener('resize', handleResize);
})

onUnmounted(() => {
  forceSaveToLocalStorage();
  
  if (refreshTimer.value) {
    clearInterval(refreshTimer.value);
  }
  Object.values(chartInstances.value).forEach(chart => chart?.dispose());
  window.removeEventListener('resize', handleResize);
})
</script>

<style scoped>
.resource-monitor-panel {
  padding: 20px;
  background: linear-gradient(135deg, #0c0e1a 0%, #1a1f35 50%, #0f1220 100%);
  min-height: 100vh;
  color: #fff;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.resource-monitor-panel h2 {
  text-align: center;
  font-size: 2.2em;
  margin-bottom: 30px;
  background: linear-gradient(45deg, #00f2fe, #9d50bb);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  text-shadow: 0 0 30px rgba(79, 172, 254, 0.5);
}

/* 控制栏样式 */
.control-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding: 15px 20px;
  background: rgba(16, 18, 27, 0.8);
  border-radius: 12px;
  border: 1px solid rgba(79, 172, 254, 0.3);
  backdrop-filter: blur(10px);
}

.search-box {
  flex: 1;
  max-width: 300px;
}

.control-buttons {
  display: flex;
  gap: 10px;
  margin: 0 20px;
}

/* 状态栏样式 */
.status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  background: rgba(16, 18, 27, 0.8);
  border-radius: 12px;
  border: 1px solid rgba(79, 172, 254, 0.2);
  margin-bottom: 20px;
  backdrop-filter: blur(10px);
}

.update-time {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9em;
}

.device-count {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9em;
  background: rgba(79, 172, 254, 0.1);
  padding: 4px 8px;
  border-radius: 6px;
  border: 1px solid rgba(79, 172, 254, 0.3);
}

.status-indicator {
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 0.9em;
  font-weight: bold;
  transition: all 0.3s ease;
  border: 1px solid transparent;
}

.status-initial {
  background: rgba(79, 172, 254, 0.1);
  border-color: rgba(79, 172, 254, 0.3);
  color: #4facfe;
}

.status-loading {
  background: rgba(255, 193, 7, 0.1);
  border-color: rgba(255, 193, 7, 0.3);
  color: #ffc107;
}

.status-normal {
  background: rgba(0, 255, 136, 0.1);
  border-color: rgba(0, 255, 136, 0.3);
  color: #00ff88;
}

.status-error {
  background: rgba(255, 107, 107, 0.1);
  border-color: rgba(255, 107, 107, 0.3);
  color: #ff6b6b;
}

.status-indicator:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* 调试信息样式 */
.debug-info {
  background: rgba(255, 107, 107, 0.1);
  border: 1px solid rgba(255, 107, 107, 0.3);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 20px;
  backdrop-filter: blur(10px);
}

.debug-info p {
  margin: 5px 0;
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.9em;
}

.debug-info button {
  background: rgba(79, 172, 254, 0.2);
  border: 1px solid rgba(79, 172, 254, 0.4);
  color: #4facfe;
  padding: 6px 12px;
  border-radius: 6px;
  margin-right: 10px;
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: 0.85em;
}

.debug-info button:hover {
  background: rgba(79, 172, 254, 0.3);
  transform: translateY(-1px);
}

/* 设备列表样式 */
.device-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* 错误和空状态 */
.error-state, .empty-state {
  text-align: center;
  padding: 60px 20px;
  background: rgba(16, 18, 27, 0.8);
  border-radius: 12px;
  border: 2px dashed rgba(255, 107, 107, 0.3);
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition: all 0.3s ease;
}

.error-state:hover {
  background: rgba(255, 107, 107, 0.1);
  border-color: rgba(255, 107, 107, 0.5);
  transform: translateY(-2px);
}

.error-state i, .error-state span {
  color: #ff6b6b;
  font-size: 1.2em;
  margin: 0 5px;
}

/* 设备卡片样式 */
.device-card {
  background: rgba(16, 18, 27, 0.8);
  border-radius: 16px;
  border: 1px solid rgba(79, 172, 254, 0.3);
  padding: 20px;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.device-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(79, 172, 254, 0.1), transparent);
  transition: left 0.5s;
}

.device-card:hover::before {
  left: 100%;
}

.device-card:hover {
  transform: translateY(-5px);
  border-color: rgba(79, 172, 254, 0.6);
  box-shadow: 0 10px 30px rgba(0, 242, 254, 0.2);
}

/* 设备头部 */
.device-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid rgba(79, 172, 254, 0.2);
}

.device-info {
  flex: 1;
}

.device-id {
  margin: 0 0 8px 0;
  font-size: 1.3em;
  color: #00f2fe;
  font-weight: bold;
}

.device-meta {
  display: flex;
  align-items: center;
  gap: 10px;
}

.device-type {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.95em;
  background: rgba(79, 172, 254, 0.1);
  padding: 4px 8px;
  border-radius: 6px;
  border: 1px solid rgba(79, 172, 254, 0.3);
}

.device-status {
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 0.85em;
  font-weight: bold;
}

.status-normal {
  background: rgba(0, 255, 136, 0.1);
  border: 1px solid rgba(0, 255, 136, 0.3);
  color: #00ff88;
}

.status-warning {
  background: rgba(255, 193, 7, 0.1);
  border: 1px solid rgba(255, 193, 7, 0.3);
  color: #ffc107;
}

.status-error {
  background: rgba(255, 107, 107, 0.1);
  border: 1px solid rgba(255, 107, 107, 0.3);
  color: #ff6b6b;
}

.status-unknown {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: rgba(255, 255, 255, 0.7);
}

/* 设备统计 */
.device-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  min-width: 200px;
}

.stat-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.stat-label {
  font-size: 0.85em;
  color: rgba(255, 255, 255, 0.7);
}

.stat-value {
  font-weight: bold;
  font-size: 0.9em;
}

.high-usage {
  color: #ff6b6b;
}

.medium-usage {
  color: #ffa726;
}

.normal-usage {
  color: #00ff88;
}

/* 图表区域 */
.device-charts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.chart-section {
  background: rgba(255, 255, 255, 0.03);
  border-radius: 12px;
  border: 1px solid rgba(79, 172, 254, 0.2);
  padding: 15px;
  transition: all 0.3s ease;
}

.chart-section:hover {
  border-color: rgba(79, 172, 254, 0.5);
  background: rgba(79, 172, 254, 0.05);
}

.chart-title {
  font-size: 1em;
  color: rgba(255, 255, 255, 0.9);
  text-align: center;
  margin-bottom: 10px;
  font-weight: bold;
}

.chart-container-large {
  height: 200px;
  width: 100%;
}

/* Element Plus 组件样式覆盖 */
:deep(.el-input__wrapper) {
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(79, 172, 254, 0.3) !important;
  border-radius: 8px !important;
  box-shadow: none !important;
}

:deep(.el-input__inner) {
  color: #fff !important;
}

:deep(.el-input__inner::placeholder) {
  color: rgba(255, 255, 255, 0.5) !important;
}

:deep(.el-pagination) {
  color: rgba(255, 255, 255, 0.7) !important;
}

:deep(.el-pagination .btn-prev),
:deep(.el-pagination .btn-next),
:deep(.el-pagination .number) {
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(79, 172, 254, 0.2) !important;
  color: rgba(255, 255, 255, 0.7) !important;
}

:deep(.el-pagination .number:hover),
:deep(.el-pagination .btn-prev:hover),
:deep(.el-pagination .btn-next:hover) {
  color: #00f2fe !important;
  border-color: rgba(0, 242, 254, 0.5) !important;
}

:deep(.el-pagination .active) {
  background: linear-gradient(45deg, #00f2fe, #9d50bb) !important;
  border-color: transparent !important;
  color: #fff !important;
}

/* 动画 */
@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .device-charts {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .device-header {
    flex-direction: column;
    gap: 15px;
  }
  
  .device-stats {
    width: 100%;
  }
  
  .control-bar {
    flex-direction: column;
    gap: 15px;
  }
  
  .search-box {
    max-width: 100%;
  }
  
  .control-buttons {
    margin: 0;
  }
}

/* 滚动条样式 */
.resource-monitor-panel::-webkit-scrollbar {
  width: 6px;
}

.resource-monitor-panel::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 3px;
}

.resource-monitor-panel::-webkit-scrollbar-thumb {
  background: linear-gradient(45deg, #00f2fe, #4facfe);
  border-radius: 3px;
}

.resource-monitor-panel::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(45deg, #00f2fe, #9d50bb);
}
</style>